package com.smartboot.plus.condition;

import com.smartboot.plus.utils.Func;

import java.util.Arrays;
import java.util.Collection;

/**
 *             ConditionQ c1 = ConditionQ.like("username", "");
 *             ConditionQ c2 = ConditionQ.like("xx", "1");
 *             ConditionGroup conditionGroup=new ConditionGroup() ;
 *
 *             System.out.println(c1);
 *             System.out.println(c2);
 *
 *             conditionGroup.add(c1.and(c2));
 *             System.out.println(conditionGroup.toString());
 *
 *             ConditionQ c11 = new ConditionQ("username", "=", "admin");
 *             ConditionQ c22 = new ConditionQ("status", "=", ""); // 会被忽略
 *             ConditionQ c33 = new ConditionQ("deleted", "=", null); // 会被忽略
 *
 *             System.out.println(c11); // 输出: username = 'admin'
 *             System.out.println(c22); // 输出: 空
 *             System.out.println(c33); // 输出: 空
 *             ConditionGroup conditionGroup1=new ConditionGroup() ;
 *
 *             conditionGroup1.add(c11.and(c22).add(c33));
 *
 *             System.out.println(conditionGroup1.toString());
 */
public class ConditionQ implements Cloneable {

    /**
     * 操作符常量
     */
    public static final String EQ = "=";
    public static final String NOT_EQ = "!=";
    public static final String NE = "<>";
    public static final String LT = "<";
    public static final String LTE = "<=";
    public static final String GT = ">";
    public static final String GTE = ">=";
    public static final String LIKE = "LIKE";
    public static final String IN = "IN";
    public static final String IS_NULL = "IS NULL";
    public static final String IS_NOT_NULL = "IS NOT NULL";
    public static final String BETWEEN = "BETWEEN";

    private String column;      // 字段名
    private String operator;    // 操作符
    private Object value;       // 值

    /**
     * 构造方法（默认使用等于操作符）
     */
    public ConditionQ(String column, Object value) {
        this(column, EQ, value);
    }
    public <T> ConditionQ(SFunction<T, ?> columnLambda, Object value) {
        this(LambdaCondition.resolveFieldName(columnLambda), EQ, value);
    }

    public ConditionGroup and(ConditionQ other) {
        return new ConditionGroup(ConditionGroup.AND).add(this).add(other);
    }

    public ConditionGroup or(ConditionQ other) {
        return new ConditionGroup(ConditionGroup.OR).add(this).add(other);
    }

    /**
     * 构造方法（指定操作符）
     */
    public ConditionQ(String column, String operator, Object value) {
        if (Func.isNotEmpty(value)) {
            this.column = column;
            this.operator = normalizeOperator(operator);
            this.value = processValue(operator, value);
        }
    }
    public <T> ConditionQ(SFunction<T, ?> columnLambda, String operator, Object value) {
        this(LambdaCondition.resolveFieldName(columnLambda), operator, value);
    }


    /**
     * 操作符标准化（例如将"=="转换为"="）
     */
    private String normalizeOperator(String operator) {
        if (EQ.equalsIgnoreCase(operator) || operator.equals("==")) {
            return EQ;
        }
        if (NE.equalsIgnoreCase(operator) || operator.equals("!=")) {
            return NE;
        }
        return operator;
    }

    /**
     * 值预处理（处理集合、数组等特殊类型）
     */
    private Object processValue(String operator, Object value) {
        if (value instanceof Collection<?>) {
            return ((Collection<?>) value).toArray();
        }
        if (value.getClass().isArray()) {
            return value;
        }
        if (operator == LIKE) {
            return "'%" + value + "%'";
        }
        if (value instanceof String) {
            return "'" + value + "'";
        }
        return value;
    }

    /**
     * 生成SQL条件字符串
     */
    @Override
    public String toString() {
        if (column == null || operator == null || value == null || "".equals(value)) {
            return ""; // 不拼接任何 SQL
        }

        if (IS_NULL.equals(operator) || IS_NOT_NULL.equals(operator)) {
            return column + " " + operator;
        }

        Object displayValue = formatValue(value);
        return column + " " + operator + " " + displayValue;
    }

    /**
     * 格式化值为SQL表达式
     */
    private Object formatValue(Object value) {
        if (value == null) {
            return "";
        }

        if (value instanceof Object[]) {
            Object[] array = (Object[]) value;
            if (array.length == 0) {
                return "";
            }
            if (IN.equals(operator)) {
                return String.format("(%s)", join(array, ","));
            }
            return array[0];
        }

        if (value instanceof Collection<?>) {
            Collection<?> collection = (Collection<?>) value;
            if (collection.isEmpty()) {
                return "";
            }
            if (IN.equals(operator)) {
                return String.format("(%s)", join(collection, ","));
            }
            return collection.iterator().next();
        }

        return value;
    }
    public static ConditionQ eq(String column, Object value) {
        return new ConditionQ(column, EQ, value);
    }
    /**
     * 静态工厂方法：创建LIKE条件
     */
    public static ConditionQ like(String column, Object value) {
        return new ConditionQ(column, LIKE, value);
    }

    /**
     * 静态工厂方法：创建IN条件
     */
    public static ConditionQ in(String column, Collection<?> values) {
        return new ConditionQ(column, IN, values);
    }

    /**
     * 静态工厂方法：创建BETWEEN条件
     */
    public static ConditionQ between(String column, Object min, Object max) {
        return new ConditionQ(column, BETWEEN, new Object[]{min, max});
    }
    public static <T> ConditionQ eq(SFunction<T, ?> columnLambda, Object value) {
        String column = LambdaCondition.resolveFieldName(columnLambda);
        return new ConditionQ(column, EQ, value);
    }

    public static <T> ConditionQ like(SFunction<T, ?> columnLambda, Object value) {
        String column = LambdaCondition.resolveFieldName(columnLambda);
        return new ConditionQ(column, LIKE, value);
    }

    public static <T> ConditionQ in(SFunction<T, ?> columnLambda, Collection<?> values) {
        String column = LambdaCondition.resolveFieldName(columnLambda);
        return new ConditionQ(column, IN, values);
    }
    // Getter/Setter
    public String getColumn() {
        return column;
    }

    public void setColumn(String column) {
        this.column = column;
    }

    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    /**
     * 克隆方法
     */
    @Override
    public ConditionQ clone() {
        try {
            ConditionQ clone = (ConditionQ) super.clone();
            clone.setColumn(this.column);
            clone.setOperator(this.operator);
            clone.setValue(this.value);
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 数组或集合转字符串（逗号分隔）
     */
    private String join(Iterable<?> iterable, String delimiter) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Object item : iterable) {
            if (!first) sb.append(delimiter);
            sb.append(item);
            first = false;
        }
        return sb.toString();
    }

    private String join(Object[] array, String delimiter) {
        return join(Arrays.asList(array), delimiter);
    }
}